package com.open.capacity.points.service.impl;

import cn.hutool.core.util.StrUtil;
import com.open.capacity.common.constant.PointsRuleConstant;
import com.open.capacity.common.exception.service.ServiceException;
import com.open.capacity.common.model.PointsLog;
import com.open.capacity.common.model.PointsRule;
import com.open.capacity.common.model.SysUser;
import com.open.capacity.common.web.Result;
import com.open.capacity.points.constant.PointsRuleTypeConstant;
import com.open.capacity.points.dao.PointsLogDao;
import com.open.capacity.points.dto.DateQuery;
import com.open.capacity.points.service.PointsRuleService;
import com.open.capacity.points.service.PointsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

@Service
public class PointsServiceImpl implements PointsService {

    @Resource
    private PointsLogDao pointsLogDao;
    @Resource
    private PointsRuleService pointsRuleService;

    @Override
    public Integer findCurrentPoints(SysUser user) {
        int points = 0;
        if (Objects.nonNull(user)) {
            if (!StrUtil.hasBlank(user.getUsername())) {
                points = pointsLogDao.selectCurrentPointsByUsername(user.getUsername());
            } else if (Objects.nonNull(user.getId())) {
                points = pointsLogDao.selectCurrentPointsByUserId(user.getId());
            }
        }
        return points;
    }

    @Override
    public Result findObtainPoints(Long userId) throws ServiceException {
        try {
            Integer points = findObtainPointsByDate(userId, null);
            return Result.succeed(points, "累计获得积分");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Result findTodayObtainPoints(Long userId) throws ServiceException {
        try {
            DateQuery dateQuery = DateQuery.builder().startDate(new Date()).build();
            Integer points = findObtainPointsByDate(userId, dateQuery);
            return Result.succeed(points, "今日获得积分");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Result findConsumePoints(Long userId) throws ServiceException {
        try {
            Integer points = findConsumePointsByDate(userId, null);
            return Result.succeed(points, "累计消费积分");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Result findTodayConsume(Long userId) throws ServiceException {
        try {
            DateQuery dateQuery = DateQuery.builder().startDate(new Date()).build();
            Integer points = findConsumePointsByDate(userId, dateQuery);
            return Result.succeed(points, "今日消费积分");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public Integer findObtainPointsByDate(Long userId, DateQuery dateQuery) {
        Integer result = pointsLogDao.selectPointsByCondition(userId, PointsRuleTypeConstant.OBTAIN, dateQuery);
        return result == null ? 0 : result;
    }

    @Override
    public Integer findConsumePointsByDate(Long userId, DateQuery dateQuery) {
        Integer result = pointsLogDao.selectPointsByCondition(userId, PointsRuleTypeConstant.CONSUME, dateQuery);
        return result == null ? 0 : result;
    }

    @Override
    @Transactional
    public Result change(Long userId, String pointsRuleCode, int points) throws ServiceException {
        try {
            PointsRule pointsRule = pointsRuleService.findRuleByCode(pointsRuleCode);  // 触发的积分规则
            Integer prouid = pointsRule.getPoruid();       // 积分规则id
            String prtype = pointsRule.getPrtype();        // 积分规则类型 （限制、消费、获得）
            Integer rulePoints = pointsRule.getPoints();   // 积分规则对应的积分值
            // 获取当前积分
            int currentPoints = pointsLogDao.selectCurrentPointsByUserId(userId);
            points = points < 0 ? 0 : points;
            // 判断积分规则类型
            if (prtype.equals(PointsRuleTypeConstant.OBTAIN)) {
                // 积分值校验
                int limitPoints = pointsRuleService.findRuleByCode(PointsRuleConstant.POINTS_LIMIT_OF_DAY).getPoints();  // 查询每日获取积分限制
                Integer todayObtainPoints = (Integer) findTodayObtainPoints(userId).getData();                   // 查询今日获得积分
                if (todayObtainPoints >= limitPoints) return Result.failed("今日获取积分已上限");
                points += currentPoints + rulePoints;
            } else if (prtype.equals(PointsRuleTypeConstant.CONSUME)) {
                points = currentPoints - (points + rulePoints);
                if (points < 0) return Result.failed("剩余积分不足");
            }
            PointsLog pointsLog = PointsLog.builder().poruid(prouid).points(points).points(points).userid(userId).build();
            pointsLogDao.insert(pointsLog);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return Result.succeed(points, "操作成功，当前积分");
    }
}
